#
# npm install websocket (websocket-node.js)
# npm install underscore (underscore.js)
#

#
# Define
#
DEBUG = true
SERVER_HOST = null
SERVER_PORT = 3000


_und = require('underscore')

# logger 
logger = (msg)->
  console.log (new Date()) + msg

g_settings = {
  SERVER_HOST: null,
  SERVER_PORT: 3000,
  KEEPALIVE_INT: 30000
}

# @todo need manage count in Database
g_usercount = 0

#
# class streaming server
#
class StreamServer
  settings: null
  http_server: null
  socket_server: null

  #
  # constructor
  #
  constructor:(@settings)->

  #
  # server setup
  #
  start_server:->
    @http_server = require('http').createServer((request, response) ->
        logger ' HTTP request for ' + request.url
        response.writeHead(404)
        response.end()
    )
    @http_server.listen @settings.SERVER_PORT, @settings.SERVER_HOST

    # Web Socket 
    WebSocketServer = require('websocket').server
    @socket_server = new WebSocketServer({
          httpServer: @http_server,
          autoAcceptConnections: false,
          keepalive: true,
          keepaliveInterval: @settings.KEEPALIVE_INT
      })

    # socket: on try connection
    @socket_server.on 'request', (request)=>
      @on_connection_requested(request)

    # socket: on connection established
    @socket_server.on 'connect', (client)=>
      @on_connection_established(client)

  #
  # send broadcast : json stringify data
  #
  send_connection_utf8:(conn, utf_data)->
    conn.sendUTF(utf_data)

  #
  # send broadcast : json stringify data
  #
  send_broadcast_utf8:(utf_data)->
    @socket_server.connections.forEach (connection, i, ary)=>
      @send_connection_utf8(connection, utf_data)

  #
  # socket: on try connection
  # parameter is WebSocketRequest
  #
  on_connection_requested:(request)->
    logger 'Connection Request from ' + request.origin

    # @todo check allowed
    request.accept(null, request.origin)

  #
  # socket: on connection established
  # parameter is WebSocketConnection
  #
  on_connection_established:(client)->
    client.on 'message', (message)=>
      switch message.type
        when 'utf8'
          # json data
          js_msg = JSON.parse(message.utf8Data)
          @on_receive_json(client, js_msg)

        when 'binary'
          # binary data (Streaming PCM)
          @socket_server.connections.forEach (connection, i, ary)->
            connection.sendBytes(message.binaryData);

        else 
          logger "Error : unknown message type #{message.type}"

  #
  # socket: on receive json
  #
  on_receive_json:(client, js_data)->
    switch js_data.type
      when 'try_authorize'
        # @todo check wheterh username and roomid is correct from
        # data requested by room master
        # @todo user count is managed by database
        g_usercount++
        reply_js = JSON.stringify({
          type: 'authorized',
          session_id: g_usercount
        })
        @send_connection_utf8(client, reply_js)
        logger "User authorized id=#{g_usercount}"

      when 'to_add_tune'
        # @todo modify tunelist (redis)
        reply_js = JSON.stringify({
          type: 'added_tune',
          tune_name: js_data.tune_name,
          owner_session_id: js_data.session_id
        })
        # @todo need to limit room id
        @send_broadcast_utf8 reply_js
        logger "to_add_tune name=#{js_data.tune_name}"

      when 'start_playing'
        # @todo modify tunelist (redis)
        reply_js = JSON.stringify({
          type: 'started_playing',
          tune_name: js_data.tune_name,
          owner_session_id: js_data.session_id
          requester_id: js_data.requester_id
        })
        # @todo need to limit room id
        @send_broadcast_utf8 reply_js
        logger "start_playing name=#{js_data.tune_name} requester=#{js_data.requester_id}"

      when 'finish_publishing'
        reply_js = JSON.stringify({
          type: 'finished_publishing',
          tune_name: js_data.tune_name,
          owner_session_id: js_data.session_id
        })
        # @todo need to limit room id
        @send_broadcast_utf8 reply_js
        logger "finish_publishing owner_id=#{js_data.session_id}"

      else 
        logger "Error : unknown json type #{js_data.type}"



# main
g_server = new StreamServer(g_settings)
g_server.start_server()

